package rd.hardcore.engine.datas 
{
	import flash.events.Event;
	import flash.events.EventDispatcher;
	import flash.events.IOErrorEvent;
	import flash.net.URLLoader;
	import flash.net.URLRequest;
	import fr.digitas.flowearth.conf.Conf;
	import rd.hardcore.datas.Track;
	import rd.hardcore.engine.datas.streamBoard.BoardSynchroEngine;
	import rd.hardcore.engine.datas.streamBoard.StreamBoardEvent;
	import rd.hardcore.engine.datas.streamBoard.StreamBoardState;
	import rd.hardcore.engine.datas.streamBoard.StreamBoardStateEvent;
	import rd.hardcore.engine.datas.streamBoard.StreamBoardSynchroEvent;
	
	/**
	 * ...
	 * @author Fazermokeur
	 */
	public class StreamBoardManager extends EventDispatcher
	{
		public static const NO_STREAM_BOARD		: String = "no_streamBoard";
		public static const PENDING				: String = "pending";
		public static const STREAM_BOARD_READY 	: String = "stream_board_ready";
		
		private var _STREAM_BOARD_NAME 			: String;
		private var _STATE						: String;
		private var _STREAM_COUNT				: int = 0;
		
		private var _vPads						: Vector.<Track>;
		private var _vGrid						: Vector.<StreamBoardData>;
		
		private var navMediaURL 				: String;
		private var background					: String;
		
		public function StreamBoardManager() 
		{
			if( instance != null ) throw new Error( "rd.hardcore.engine.datas.StreamBoardManager est deja instanciée" );
		}
		
		
		/**
		 * Vérifie si une streamBoard existe
		 */
		public function checkForBoard():void
		{
			
			_vGrid = new Vector.<StreamBoardData>();
			
			_STATE = PENDING;
			var l:URLLoader = new URLLoader();
			l.addEventListener(IOErrorEvent.IO_ERROR, handleIOError);
			l.addEventListener(Event.COMPLETE, handleCheckFileLoaded);
			l.load(new URLRequest(Conf.getString("mainStreamBoard")));
		}
		
		private function handleCheckFileLoaded(e:Event):void 
		{
			var l:URLLoader = e.currentTarget as URLLoader;
			l.removeEventListener(IOErrorEvent.IO_ERROR, handleIOError);
			l.removeEventListener(Event.COMPLETE, handleCheckFileLoaded);
			
			try {
				var d:XMLList = new XMLList(l.data);
				if (d.board[0]) {
					trace("2:_STATE = PENDING, there are " + d.board.length() + " Fkng boards");
					_STREAM_COUNT = d.board.length();
					_STATE = PENDING;
					var node:XML;
					var sData:StreamBoardData;
					for each(node in d.board) {
						sData = new StreamBoardData(node.boardName, node.labelName);
						sData.addEventListener(StreamBoardStateEvent.STATE_CHANGE, handleStateChange);
						_vGrid.push(sData);
					}
					
					activeState = new StreamBoardState(_vGrid);
					
					engine = new BoardSynchroEngine();
					engine.addEventListener(StreamBoardSynchroEvent.STREAMBOARD_SYNCHONIZED, buildDatas);
					engine.setDatas(d);
				}else {
					trace("3:_STATE = NO_STREAM_BOARD");
					_STATE = NO_STREAM_BOARD;
				}
			}catch (e:Error) {
				trace("3:ERROR::Lors de la création des données");
				createFromBoardState();
			}
			
			//var len:int =  _vGrid.length;
			//for (var i:int = 0; i < len; i++) 
			//{
				//_vGrid[i].addEventListener(StreamBoardStateEvent.STATE_CHANGE, handleStateChange);
			//}
			l = null;
			
		}
		
		private function handleStateChange(e:StreamBoardStateEvent):void 
		{
			trace("2:H A N D L E  S T A T E  C H A N GE");
			if (activeState)	activeState.setState();
			dispatchEvent(new Event(Event.CHANGE));
		}
		
		private function buildDatas(e:StreamBoardSynchroEvent):void 
		{
			countBoard++;
			getStreamBoardData(e.name).buildDatas(e);
			activeState.setState();
			if (countBoard == _STREAM_COUNT) {
				_STATE = STREAM_BOARD_READY;
				dispatchEvent(new StreamBoardEvent(StreamBoardEvent.BOARD_READY_TO_DISPLAY));
			}
			sortActiveGrid();
		}
		
		private function sortActiveGrid():void
		{
			var _v:Vector.<StreamBoardData> = new Vector.<StreamBoardData>();
			var len:int = _vGrid.length;
			for (var i:int = 0; i < len; i++) 
			{
				if(_vGrid[0].active){
					_vGrid.push(_vGrid.shift());
				}else {
					_v.push(_vGrid.shift());
				}
			}
			len = _v.length
			for (i = 0; i < len; i++) 
			{
				_vGrid.push(_v.pop());
			}
		}
		
		public function getNavMedia (idx:int) : String
		{
			idx -= 4;
			var data:StreamBoardData = getStreamBoardData(_vGrid[idx].id);
			if (data)	return data.navMediaURL;
			else		return "";
		}
		
		public function getBackground (idx:int) : String
		{
			idx -= 4;
			var data:StreamBoardData = getStreamBoardData(_vGrid[idx].id);
			if (data)	return data.background;
			else		return "";
		}
		
		private function getStreamBoardData(id:String):StreamBoardData
		{
			var len:int = _vGrid.length;
			for (var i:int = 0; i < len; i++) 
			{
				if (_vGrid[i].id == id) {
					return _vGrid[i];
				}
			}
			return null;
		}
		
		public function isActiveById(idx:int):Boolean
		{
			idx -= 4;
			sortActiveGrid();
			var data:StreamBoardData = getStreamBoardData(_vGrid[idx].id);
			if (data)	return data.active;
			else		return false;
		}
		
		/**
		 * Génération du XML pour écriture dans pads.xml
		 * @return	contenu du noeud data
		 */
		public function getPadsXML():XML
		{
			var node:XML = <pads/>;
			var len:int = _vGrid.length;
			for (var i:int = 0; i < len; i++) 
			{
				node.appendChild(_vGrid[i].getPadManagerNode(4+i));
			}
			
			return node;
		}
		
		
		public function getTrackById(keyId:int):Track
		{
			var len:int = _vGrid.length;
			var t:Track;
			for (var i:int = 0; i < len; i++) 
			{
				t = _vGrid[i].getTrackById(keyId);
				if (t != null)	return t;
			}
			
			return null;
		}
		
		public function getBoardsState():XML
		{
			return activeState.generateStateXML();
		}
		
		public function setBoardsState(boardId:String):Boolean
		{
			return activeState.stateChange(boardId);
		}
		
		private function handleIOError(e:IOErrorEvent):void 
		{
			_STATE = NO_STREAM_BOARD;
			throw new Error("File or connexion doesn't exist ");
			var l:URLLoader = e.currentTarget as URLLoader;
			l.removeEventListener(IOErrorEvent.IO_ERROR, handleIOError);
			l.removeEventListener(Event.COMPLETE, handleCheckFileLoaded);
			l = null;
			
			createFromBoardState();
		}
		
		private function createFromBoardState():void
		{
			activeState = new StreamBoardState(null);
			_vGrid = activeState.getDataVector();
			var len:int =  _vGrid.length;
			for (var i:int = 0; i < len; i++) 
			{
				_vGrid[i].addEventListener(StreamBoardStateEvent.STATE_CHANGE, handleStateChange);
			}
			_STREAM_COUNT = len;
			
			_STATE = STREAM_BOARD_READY;
		}
		
		
		
			
		//_____________________________________________________________________________
		//																		 SINGLETON
		
		public static var instance : StreamBoardManager;
		private var engine:BoardSynchroEngine;
		private var activeState:StreamBoardState;
		//private var totalBoard:int;
		private var countBoard:int = 0;
		
		public static function start( ) : StreamBoardManager {
			if (instance == null)
				instance = new StreamBoardManager();
			return instance;
		}
		
		public function get STREAM_BOARD_NAME():String { return _STREAM_BOARD_NAME; }
		
		public function get STATE():String { return _STATE; }
		
		public function get STREAM_COUNT():int { return _STREAM_COUNT; }
		
	}

}